package org.foj.presenter {

import mx.collections.ArrayCollection;
import mx.controls.Alert;
import mx.core.UIComponent;
import mx.managers.CursorManager;
import mx.managers.PopUpManager;
import mx.rpc.AsyncResponder;
import mx.rpc.AsyncToken;
import mx.rpc.events.FaultEvent;
import mx.rpc.events.ResultEvent;

import org.foj.dto.Comment;
import org.foj.dto.Issue;
import org.foj.dto.User;
import org.foj.event.EventDispatcherFactory;
import org.foj.event.UIEvent;
import org.foj.event.UserEvent;
import org.foj.model.CommentModel;
import org.foj.view.CommentsView;
import org.foj.view.EditCommentForm;

public class CommentsListPresenter {

  private var _currentUser:User;
  private var _selectedIssue:Issue;
  private var _selectedComment:Comment;
  private var _commentModel:CommentModel;
  private var _view:CommentsView;
  private var _pop1:EditCommentForm;

  public function CommentsListPresenter(view:CommentsView = null) {
    this._commentModel = new CommentModel();

    this._view = view;

    EventDispatcherFactory.getEventDispatcher()
        .addEventListener(UIEvent.SELECTED_ISSUE_CHANGED,
        changeSelectedIssue);
    EventDispatcherFactory.getEventDispatcher()
        .addEventListener(UIEvent.ADD_NEW_COMMENT_BUTTON_PRESSED,
        addNewComment);
    EventDispatcherFactory.getEventDispatcher()
        .addEventListener(UIEvent.EDIT_COMMENT_BUTTON_PRESSED,
        editComment);
    EventDispatcherFactory.getEventDispatcher()
        .addEventListener(UIEvent.DELETE_COMMENT_BUTTON_PRESSED,
        removeComment);
    EventDispatcherFactory.getEventDispatcher()
        .addEventListener(UIEvent.SELECTED_COMMENT_CHANGED,
        changeSelectedComment);
    EventDispatcherFactory.getEventDispatcher()
        .addEventListener(UIEvent.COMMENTS_UPDATED,
        refreshComments);
    EventDispatcherFactory.getEventDispatcher()
        .addEventListener(UIEvent.SAVE_COMMENT_BUTTON_PRESSED,
        saveComment);
    EventDispatcherFactory.getEventDispatcher()
        .addEventListener(UIEvent.CANCEL_EDIT_COMMENT_BUTTON_PRESSED,
        cancelEdit);
    EventDispatcherFactory.getEventDispatcher()
        .addEventListener(UserEvent.CURRENT_USER_UPDATED,
        currentUserChanged);
  }

  private function get selectedIssue():Issue {
    return this._selectedIssue;
  }

  private function set selectedIssue(issue:Issue):void {
    this._selectedIssue = issue;
    _view.addCommentButton.enabled = issue.id > 0;
  }

  private function get selectedComment():Comment {
    return this._selectedComment;
  }

  private function set selectedComment(comment:Comment):void {
    this._selectedComment = comment;
    _view.editCommentButton.enabled = comment != null;
    _view.deleteCommentButton.enabled = comment != null;
  }

  private function changeSelectedIssue(event:UIEvent):void {
    selectedIssue = event.data;
    selectedComment = null;
    refreshComments();
  }

  private function changeSelectedComment(event:UIEvent):void {
    selectedComment = event.data;
  }

  private function addNewComment(event:* = null):void {
    selectedComment = new Comment();
    selectedComment.issue = selectedIssue;

    _pop1 = PopUpManager.createPopUp((_view as UIComponent).root,
        EditCommentForm, true) as EditCommentForm;
    _pop1.author.text = _currentUser.fullName;
    PopUpManager.centerPopUp(_pop1 as UIComponent);
  }

  private function editComment(event:* = null):void {
    _pop1 = PopUpManager.createPopUp((_view as UIComponent).root,
        EditCommentForm, true) as EditCommentForm;
    PopUpManager.centerPopUp(_pop1 as UIComponent);
    _pop1.author.text = selectedComment.author;
    _pop1.commentDate.selectedDate = selectedComment.createdDate;
    _pop1.commentText.text = selectedComment.commentText;
  }

  private function removeComment(event:* = null):void {
    CursorManager.setBusyCursor();
    _commentModel.removeComment(selectedComment.id,
        new AsyncResponder(removeCommentResult, handleError));
  }

  private function refreshComments(event:* = null):void {
    CursorManager.setBusyCursor();
    _commentModel.getCommentsForIssueId(selectedIssue.id,
        new AsyncResponder(loadCommentsResult, handleError));
  }

  private function saveComment(event:* = null):void {
    CursorManager.setBusyCursor();
    selectedComment.author = _pop1.author.text;
    selectedComment.createdDate = _pop1.commentDate.selectedDate;
    selectedComment.commentText = _pop1.commentText.text;

    _commentModel.saveComment(selectedComment,
        new AsyncResponder(saveCommentResult, handleError));
  }

  private function cancelEdit(event:* = null):void {
    removePopUp();
  }

  private function removeCommentResult(event:ResultEvent,
                                       token:AsyncToken = null):void {
    CursorManager.removeBusyCursor();
    refreshComments();
  }

  private function saveCommentResult(event:ResultEvent,
                                     token:AsyncToken = null):void {
    CursorManager.removeBusyCursor();
    selectedComment = event.result as Comment;
    var commentsChangedEvent:UIEvent = new UIEvent(UIEvent.COMMENTS_UPDATED);
    EventDispatcherFactory.getEventDispatcher()
        .dispatchEvent(commentsChangedEvent);
    removePopUp();
  }

  private function loadCommentsResult(event:ResultEvent,
                                      token:AsyncToken = null):void {
    CursorManager.removeBusyCursor();
    var comments:ArrayCollection = new ArrayCollection();
    for each (var result:* in event.result) {
      comments.addItem(new Comment(result));
    }
    _view.commentsList.dataProvider = comments;
    _view.commentsList.selectedIndex = -1;
    selectedComment = null;
  }

  private function currentUserChanged(event:UserEvent):void {
    _currentUser = event.data;
  }

  private function handleError(event:FaultEvent,
                               token:AsyncToken = null):void {
    CursorManager.removeBusyCursor();
    Alert.show(event.fault.faultString);
  }

  private function removePopUp():void {
    PopUpManager.removePopUp(_pop1 as UIComponent);
  }

}
}